// 链表的设计者

#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

/*使用者可以自定义宏 DATATYPE, 令其为用户需要的类型
  否则，默认存储 int */ 

// #ifndef DATATYPE
#define DATATYPE int // 链表节点的默认数据类型
// #endif

typedef DATATYPE datatype;

struct node
{
    datatype data;
    struct node *next;
};

// 初始化一个带头结点的空单链表
static struct node *init_list()
{
    struct node *head = calloc(1, sizeof(struct node));
    if(head != NULL)
    {
        head->next = NULL;
    }
    return head;
}

static struct node *new_node(datatype data,
                             void (*f)(datatype *, datatype))
{
    struct node *new = calloc(1, sizeof(struct node));
    if(new != NULL)
    {
        if(f == NULL)
            new->data = data;
        else
            f(&new->data, data); // new->data <-- data

        new->next = NULL;
    }
    return new;
}

static void add_list(struct node *head, struct node *new)
{
    new->next = head->next;
    head->next = new;
}

static void list_for_each(struct node *head, void (*f)(datatype data))
{
    for(struct node *p = head->next; p!=NULL; p=p->next)
    {
        f(p->data); // 交给用户去处理data
    }
}

// 查找某个节点
static struct node *find(struct node *head, datatype data,
                         bool (*equal)(datatype, datatype) )
{
    for(struct node *p=head->next; p!=NULL; p=p->next)
    {
        // 如果用户未提供数据比对回调函数，则直接比较他们
        if(equal == NULL)
        {
            if(p->data == data)
                return p;
        }
        // 否则调用用户提供的回调函数，来比对两个数据
        else
        {
            if(equal(p->data, data))
                return p;
        }
    }
    return NULL;
}

#endif